package com.handpay.framework.swiper.landi;

import android.content.Context;
import android.graphics.Bitmap;
import android.text.TextUtils;
import android.util.Log;

import com.handpay.framework.ClientEngine;
import com.handpay.framework.swiper.IBusinessSwiper;
import com.handpay.framework.swiper.ISwiperListener;
import com.handpay.framework.swiper.SwiperMode;
import com.handpay.framework.swiper.SwiperModel;
import com.handpay.framework.utils.CommonUtils;
import com.handpay.zztong.hp.R;
import com.handpay.zztong.hp.other.activity.ShowHtmlActivity;
import com.handpay.zztong.hp.config.ZZTConstant;
import com.handpay.zztong.hp.log.HPLog;
import com.landicorp.android.mpos.reader.HandPayMPOS;
import com.landicorp.android.mpos.reader.PBOCOnlineDataProcessListener;
import com.landicorp.android.mpos.reader.PBOCStartListener;
import com.landicorp.android.mpos.reader.model.InputPinParameter;
import com.landicorp.android.mpos.reader.model.OnlineDataProcessResult;
import com.landicorp.android.mpos.reader.model.PBOCOnlineData;
import com.landicorp.android.mpos.reader.model.StartPBOCParam;
import com.landicorp.android.mpos.reader.model.StartPBOCResult;
import com.landicorp.mpos.reader.BasicReaderListeners.CalcMacListener;
import com.landicorp.mpos.reader.BasicReaderListeners.CancleTradeListener;
import com.landicorp.mpos.reader.BasicReaderListeners.CardType;
import com.landicorp.mpos.reader.BasicReaderListeners.CloseDeviceListener;
import com.landicorp.mpos.reader.BasicReaderListeners.EMVProcessListener;
import com.landicorp.mpos.reader.BasicReaderListeners.GetPANListener;
import com.landicorp.mpos.reader.BasicReaderListeners.GetTrackDataCipherListener;
import com.landicorp.mpos.reader.BasicReaderListeners.GetUserDataListener;
import com.landicorp.mpos.reader.BasicReaderListeners.InputPinListener;
import com.landicorp.mpos.reader.BasicReaderListeners.LoadSessionDataListener;
import com.landicorp.mpos.reader.BasicReaderListeners.OpenDeviceListener;
import com.landicorp.mpos.reader.BasicReaderListeners.WaitCardType;
import com.landicorp.mpos.reader.BasicReaderListeners.WaitingCardListener;
import com.landicorp.mpos.reader.BasicReaderListeners.getKey13EncListener;
import com.landicorp.mpos.reader.model.MPosEMVProcessResult;
import com.landicorp.robert.comm.api.DeviceInfo;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class LandiSwiperBT implements IBusinessSwiper {
	private static final String TAG = "landiSwiperBT";
	private static final String BANK_ACCOUNT_HASH_KEY = "account_hash";
	public static boolean isSwiperCard = false;
	private boolean OptResult;
	private Object objDelay = new Object();

	private DeviceInfo deviceInfo;
	protected HandPayMPOS reader;
	private AsynSwiperLock mLock;
	private String btData;
	private volatile boolean mIsSwiperOK = true;

	SwipeResult swipeResult;
	CardType swipCardType;

	private Hashtable<String, String> mHTData = new Hashtable<String, String>();

	// 用于获取字符串
	private Context mContext;

	public LandiSwiperBT(Context context, String address) {
		deviceInfo = AipSharedPreferences.getInstance(context).getDeviceInfo();
		reader = HandPayMPOS.getInstance(context);
		mLock = new AsynSwiperLock();
		mContext = context;
		reader.openDevice(deviceInfo, new OpenDeviceListener() {
			@Override
			public void openSucc() {
				HPLog.i(TAG, "打开设备成功: " + deviceInfo.getName());
				mIsSwiperOK = true;
			}

			@Override
			public void onError(int errCode, String errDesc) {
				mIsSwiperOK = false;
				HPLog.e(TAG, "打开设备失败: " + errCode + " : " + errDesc);
			}
		});

	}

	@Override
	public String getCSN() {
		HPLog.i(TAG, "READER: " + reader);
		if (reader != null) {
			reader.getUserData(3, new GetUserDataListener() {
				@Override
				public void onError(int errCode, String errDesc) {
					HPLog.i(TAG, "读取CSN号失败" + errDesc);
					mIsSwiperOK = false;
					mLock.unlock(AsynSwiperLock.GETCSN);
				}

				@Override
				public void onGetUserDataSucc(String result) {
					HPLog.i(TAG, "onGetUserDataSucc" + result);
					btData = result;
					mLock.unlock(AsynSwiperLock.GETCSN);
				}
			}, ZZTConstant.SWIPER_TIMEOUT);
		} else {
			mLock.unlock(AsynSwiperLock.GETCSN);
		}

		try {
			mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.GETCSN);
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
		}

		return btData;
	}

	@Override
	public boolean stopOperation() {
		HPLog.i(TAG, "stopOperation>>>>>");
		OptResult = true;
		mAmount = "";
		Emtd2 = "";
		isSwiperCard = false;
		reader.cancleTrade(new CancleTradeListener() {

			@Override
			public void onError(int errCode, String errDesc) {
				HPLog.i(TAG, "cancleTrade fail");
				OptResult = false;
			}

			@Override
			public void onCancleTradeSucc() {
				HPLog.i(TAG, "cancleTrade success");
				OptResult = true;
			}
		});

		// 给设备完成取消动作足够的响应时间
		synchronized (objDelay) {
			try {
				objDelay.wait(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		return OptResult;
	}

	@Override
	public boolean closeDevice() {
		OptResult = false;
		if (reader != null) {
			reader.closeDevice(new CloseDeviceListener() {
				@Override
				public void closeSucc() {
					HPLog.i(TAG, "closeDevice success");
					mContext = null;
					reader = null;
					OptResult = true;
					// mLock.unlock(AsynSwiperLock.CLOSE_DEVICE);
				}
			});
		}
		// try {
		// mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CLOSE_DEVICE);
		// } catch (TimeoutException te) {
		// HPLog.i(TAG, "", te);
		// }

		synchronized (objDelay) {
			try {
				objDelay.wait(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		return OptResult;
	}

	private void clearScreen() {

	}

	/**
	 * 获取随机数
	 * 
	 * @param length
	 * @return
	 */
	public static byte[] getRandom(int length) {
		if (length < 1) {
			return null;
		}
		Random random = new Random();
		byte[] bytes = new byte[length];
		random.nextBytes(bytes);
		return bytes;
	}

	public static byte[] getDynamicKeyData() {
		try {
			byte[] rand = getRandom(8);
			// FIX RANDOM
			// rand = CommonUtils.hexStringToBytes("08745B3041F93398");
			return rand;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	String deviceRandomNumber = "";

	public String GetDeviceRandomNumber() {
		// 获取随机数
		reader.getUserData(4, new GetUserDataListener() {
			@Override
			public void onError(int errCode, String errDesc) {
				HPLog.i(TAG, "读取随机数失败" + errDesc);
				mLock.unlock(AsynSwiperLock.BIND_CARD);
			}

			@Override
			public void onGetUserDataSucc(String result) {
				HPLog.i(TAG, "读取随机数成功" + result);
				deviceRandomNumber = result;
				mLock.unlock(AsynSwiperLock.BIND_CARD);
			}
		}, ZZTConstant.SWIPER_TIMEOUT);

		try {
			mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.BIND_CARD);
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
		}

		return deviceRandomNumber.toUpperCase(Locale.US);
	}

	private boolean loadSeessionData(String factor) {
		// 先导入分散因子进行密钥分散
		if (reader != null) {
			reader.loadSessionData((byte) 0, CommonUtils.hexStringToBytes(factor), new LoadSessionDataListener() {
				@Override
				public void onError(int errCode, String errDesc) {

					OptResult = false;
					HPLog.i(TAG, "导入分散因子失败" + errDesc);
					mLock.unlock(AsynSwiperLock.LOAD_SESSION);
				}

				@Override
				public void onLoadSessionDataSucc() {
					OptResult = true;
					HPLog.i(TAG, "导入分散因子成功");
					mLock.unlock(AsynSwiperLock.LOAD_SESSION);
				}
			});
		} else {
			mLock.unlock(AsynSwiperLock.LOAD_SESSION);
		}

		try {
			mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.LOAD_SESSION);
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
		}

		return OptResult;

	}

	// private CardType getSwipResult()
	// {
	//
	// reader.waitingCard(WaitCardType.MAGNETIC_IC_CARD,
	// "0", ZZTConstant.SWIPER_TIMEOUT, new WaitingCardListener() {
	// @Override
	// public void onError(int errCode, String errDesc) {
	// HPLog.i(TAG,"刷卡错误：" + errDesc);
	// swipCardType=null;
	// mLock.unlock(AsynSwiperLock.NEW_SWIPE_CARD);
	// }
	//
	// @Override
	// public void onWaitingCardSucc(CardType cardType) {
	// HPLog.i(TAG,"刷卡成功：" + cardType.toString());
	// swipCardType = cardType;
	// mLock.unlock(AsynSwiperLock.NEW_SWIPE_CARD);
	// }
	// });
	//
	// try {
	// mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.NEW_SWIPE_CARD);
	// } catch (TimeoutException te) {
	// HPLog.i(TAG, "", te);
	// }
	//
	// return swipCardType;
	// }

	String cardPan;

	private String getPAN() {
		cardPan = "";
		reader.getPANPlain(new GetPANListener() {
			@Override
			public void onError(int errCode, String errDesc) {
				HPLog.i(TAG, "读取pan失败" + errDesc);
				mLock.unlock(AsynSwiperLock.GET_PAN);
			}

			@Override
			public void onGetPANSucc(String pan) {
				HPLog.i(TAG, "读取pan成功" + pan);
				cardPan = pan;
				mLock.unlock(AsynSwiperLock.GET_PAN);
			}
		});

		try {
			mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.GET_PAN);
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
		}

		return cardPan;
	}

	private String mDynamicKey;
	private String message;
	private String mAmount = null;
	private SwiperMode mFlag;

	private boolean isConnected() {

		OptResult = reader.isConnected();
		HPLog.i("LandiSwiperBT", Boolean.toString(OptResult));

		return OptResult;
	}

	/**
	 * 
	 * @param cardReaders
	 * @param msg
	 * @param amt
	 * @param factor
	 * @param dynamicKeyData
	 * @param timeout
	 * @param timeunit
	 * @param transferListener
	 * @return null 表示取消
	 */
	private String field55;

	private SwipeResult startTransfer(String msg, String factor, byte[] dynamicKeyData, long timeout, TimeUnit timeunit) {
		String formatAmount;
		boolean result;
		String Pan;
		HPLog.e(TAG, "-----startTransfer--------");
		waitForCard();
		HPLog.e(TAG, "-----waitForCard-------end-");
		if (!swipeResult.mStatus.equals(SwipeStatus.SWIPE_OK)) {
			if (SwipeStatus.SWIPE_TIMEOUT.equals(swipeResult.mStatus)) {
				stopOperation();
			}
			return swipeResult;
		}
		if (swipCardType.equals(CardType.MAGNETIC_CARD)) {
			Pan = getPAN();
			swipeResult.mData = Pan;
			mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY, Pan);
			result = GetCipherTrackData();
			String expireData = Emtd4;
			mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE,expireData );
			if (result == true) {
				// useless
				// mHTData.put(BANK_ACCOUNT_HASH_KEY,
				// result.getAccount().getAcctHashId());

				mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY, Emtd2.toUpperCase(Locale.US));
			}

			if (TextUtils.isEmpty(Pan) || TextUtils.isEmpty(Emtd2) || dynamicKeyData.length < 8) {
				result = false;
				HPLog.e(TAG, "PAN or dynamicKeyData or encTrack2 empty! notify re-swipe");
				swipeResult.mStatus = SwipeStatus.SWIPE_ERROR;
			} else {
				result = true;
				swipeResult.mStatus = SwipeStatus.SWIPE_OK;
			}
		} else if (swipCardType.equals(CardType.IC_CARD)) {
			if (isSwiperCard) {
				String pan = getPAN();
				if (!TextUtils.isEmpty(pan)) {
					swipeResult.mData = pan;
					swipeResult.mStatus = SwipeStatus.SWIPE_OK;
				} else {
					swipeResult.mStatus = SwipeStatus.SWIPE_TIMEOUT;
				}
			} else {

				final StartPBOCParam startPBOCParam = new StartPBOCParam();
				byte emvTradeType;
				long amount = Long.parseLong(mAmount.trim());

				if (amount == 0)
					emvTradeType = 0x31;
				else
					emvTradeType = 0;

				// 温旭东(328977974) 2014/11/28 11:18:05
				// 那金额问题跟123解释了，IC卡接口上送的金额格式和加密的金额是不一样的。IC卡上送的金额只是用来终端显示。格式应用那边可以自己转换下就可以
				if (mAmount.length() == 10) {
					formatAmount = "00" + mAmount;
				} else
					formatAmount = mAmount;

				startPBOCParam.setTransactionType(emvTradeType);
				startPBOCParam.setAuthorizedAmount(formatAmount);
				startPBOCParam.setOtherAmount("000000000000");
				String date = factor.substring(2, 8);
				String time = factor.substring(8, 14);
				startPBOCParam.setDate(date);
				startPBOCParam.setTime(time);

				// startPBOCParam.setDate("140611");
				// startPBOCParam.setTime("204409"); // "pos_time":
				startPBOCParam.setForbidContactCard(false);
				startPBOCParam.setForceOnline(true);
				startPBOCParam.setForbidMagicCard(false);
				startPBOCParam.setForbidContactlessCard(false);

				reader.startPBOC(startPBOCParam, new EMVProcessListener() {
					@Override
					public void onError(int errCode, String errDesc) {
						HPLog.i(TAG, "startPBOCOnError 读取二磁道失败:" + errDesc);
						swipeResult.mStatus = getErrorCode(errCode);
						mLock.unlock(AsynSwiperLock.PROCESS_EMV);
					}

					@Override
					public void onEMVProcessSucc(MPosEMVProcessResult result) {

						// 有效期2.0
						// 根据小微要求增加获取IC卡有效期的方法
						String expireData = result.getExpireData();

						if (CommonUtils.checkExpireDate(expireData)) {
							expireData = expireData.substring(0, 4);
							HPLog.i(HPLog.FDL_TAG, "LandiSwiper  -- plainExpireDate:" + expireData);
							mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, expireData);
						} else {
							HPLog.i(TAG, "LandiSwiper IC card but no plainExpireDate");
						}
						HPLog.i(TAG, "onEMVProcessSucc 成功 二磁道:" + result.getTrack2() + "PAN:" + result.getPan() + "ExpireDate: " + expireData);

						String tempPan = result.getPan();
						swipeResult.mData = tempPan;
						mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY, tempPan.toUpperCase(Locale.US));
						String m_panSN = result.getPanSN(); // IC Numbers
						if (!TextUtils.isEmpty(m_panSN)) {
							while (m_panSN.length() < 3) {
								m_panSN = "0" + m_panSN;
							}
							mHTData.put(BANK_ICNUMBER, m_panSN);
						}
						if (!TextUtils.isEmpty(expireData)) {
							HPLog.e(HPLog.FDL_TAG, "LandiSwiperBT:expireData---------:" + expireData);
							mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, expireData);
						}

						String tempTrack = result.getTrack2();
						if (!TextUtils.isEmpty(tempTrack)) {

							mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY, tempTrack.toUpperCase(Locale.US));
						}
					}
				}, new PBOCStartListener() {
					@Override
					public void onError(int errCode, String errDesc) {
						HPLog.i(TAG, "onPBOCStartOnError 交易失败:" + errDesc);
						swipeResult.mStatus = getErrorCode(errCode);
						/**
						 * 超时好像是由于landiSwiperBT:读取随机数失败处理超时导致
						 * 确认卡号超时会导致PBOC超时，原先弹出对话框点击确认后就直接调用刷卡而没有先做取消操作，加入以下取消操作
						 */
						stopOperation();
						mLock.unlock(AsynSwiperLock.PROCESS_EMV);
					}

					@Override
					public void onPBOCStartSuccess(StartPBOCResult result) {
						HPLog.i(TAG, "onPBOCStartSuccess");
						byte[] encPin = result.getPwdData();
						if (encPin != null && "FFFFFFFFFFFFFFFF".equalsIgnoreCase(CommonUtils.bytesToHexString(encPin))) {
							encPin = null;
						}
						if (encPin != null) {
							mHTData.put(BANK_PAN_KEY, CommonUtils.bytesToHexString(encPin).toUpperCase(Locale.US));

						} else {
							mHTData.put(BANK_PAN_KEY, "");
						}

						field55 = CommonUtils.bytesToHexString(result.getICCardData()).toUpperCase(Locale.US); // DC
																												// data
						HPLog.i(TAG, "onPBOCStartSuccess: " + field55);
						mHTData.put(BANK_DCDATA, field55);
						swipeResult.mStatus = SwipeStatus.SWIPE_OK;

						PBOCOnlineData onlineData = new PBOCOnlineData();
						String authRespCode = "00";
						onlineData.setAuthRespCode(authRespCode.getBytes());
						onlineData.setOnlineData(CommonUtils.hexStringToBytes(field55));

						reader.onlineDataProcess(onlineData, new PBOCOnlineDataProcessListener() {
							@Override
							public void onError(int errCode, String errDesc) {
								HPLog.i(TAG, "交易失败" + errDesc);
								mLock.unlock(AsynSwiperLock.PROCESS_EMV);
							}

							@Override
							public void onPBOCOnlineDataProcess(OnlineDataProcessResult arg0) {
								HPLog.i(TAG, "emv联机处理成功" + CommonUtils.bytesToHexString(arg0.getICCardData()));
								mLock.unlock(AsynSwiperLock.PROCESS_EMV);
							}
						});

					}
				});

				try {
					mLock.lock(ZZTConstant.SWIPER_TIMEOUT * 2, AsynSwiperLock.PROCESS_EMV);
				} catch (TimeoutException te) {
					HPLog.i(TAG, "", te);
					swipeResult.mStatus = SwipeStatus.SWIPE_ERROR;
				}
			}
		}

		return swipeResult;

	}

	private String transExpireDateToMMYY(String expireDate) {
		String yy = expireDate.substring(0, 2);
		String mm = expireDate.substring(2, 4);
		return mm + yy;
	}

	private void waitForCard() {
		swipCardType = null;
		swipeResult = new SwipeResult(SwipeStatus.SWIPE_ERROR);

		isConnected();
		HPLog.e(TAG, "-----waitForCard-------start-");
		reader.waitingCard(WaitCardType.MAGNETIC_IC_CARD, "0", ZZTConstant.SWIPER_TIMEOUT, new WaitingCardListener() {
			@Override
			public void onError(int errCode, String errDesc) {

				switch (errCode) {
				case 0x8E10:
					swipeResult = new SwipeResult(SwipeStatus.SWIPE_TIMEOUT);
					break;
				case 0x8E11:
					swipeResult = new SwipeResult(SwipeStatus.SWIPE_CANCEL);
					break;
				}

				HPLog.e(TAG, "错误：" + errDesc);
				mLock.unlock(AsynSwiperLock.NEW_SWIPE_CARD);
			}

			@Override
			public void onWaitingCardSucc(CardType cardType) {
				swipeResult = new SwipeResult(SwipeStatus.SWIPE_OK);
				swipCardType = cardType;
				HPLog.i(TAG, "卡片类型：" + swipCardType.name());
				mLock.unlock(AsynSwiperLock.NEW_SWIPE_CARD);
			}

			@Override
			public void onProgressMsg(String arg0) {

			}
		});

		try {
			mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.NEW_SWIPE_CARD);
		} catch (TimeoutException te) {
			swipeResult = new SwipeResult(SwipeStatus.SWIPE_TIMEOUT);
			HPLog.i(TAG, "", te);
		}
	}

	private SwipeStatus getErrorCode(int errCode) {
		SwipeStatus ss;

		switch (errCode) {
		case 0x8E10:
			ss = SwipeStatus.SWIPE_TIMEOUT;
			break;
		case 0x8E11:
			ss = SwipeStatus.SWIPE_CANCEL;
			break;
		default:
			ss = SwipeStatus.SWIPE_ERROR;
		}

		return ss;
	}

	@Override
	public SwipeResult swipeCard(String factor, int timeout) {

		swipeResult = null;

		// update by jh for test.
		// mDynamicKey = CommonUtils.bytesToHexString(getDynamicKeyData());
		mDynamicKey = GetDeviceRandomNumber();
		mHTData.clear();

		String strTimeOut = "" + timeout;
		mHTData.put("checkCardTimeout", strTimeOut);
		mHTData.put("randomNumber", factor);

		boolean result = loadSeessionData(factor);
		HPLog.e(TAG, "-----loadSeessionData------end--" + result);
		if (result != true)
			return (new SwipeResult(SwipeStatus.SWIPE_ERROR));

		try {
			// String message;
			String swipe = mContext.getString(R.string.landi_swipe);
			// 如果，用户确认过金额，显示金额。没有直接显示请刷卡
			// 如果超级转账，金额也不是显示的。
			if (TextUtils.isEmpty(mAmount) || mFlag == SwiperMode.SUPER_TRANS) {
				message = swipe;
			} else {
				BigDecimal bd = new BigDecimal(mAmount);
				bd = bd.divide(new BigDecimal("100"));
				message = mContext.getString(R.string.newland_amount) + bd.toString() + "\n" + swipe;
			}

			clearScreen();

			// SwipeResult result = null;

			// BigDecimal amt = new BigDecimal(0);
			//
			// if (!TextUtils.isEmpty(mAmount)) {
			// amt = new BigDecimal(mAmount);
			// }

			if (TextUtils.isEmpty(mAmount))
				mAmount = "0000000000";

			swipeResult = startTransfer(message, factor, CommonUtils.hexStringToBytes(mDynamicKey), timeout, TimeUnit.SECONDS);
			if (swipeResult.mStatus == SwipeStatus.SWIPE_OK) {

				// 其他的，譬如pin,卡号密文，金额密文等。输入密码后，做加密后加入。

				mHTData.put(BANK_DYNAMIC_KEY, mDynamicKey.toUpperCase(Locale.US));
				// mHTData.put(BANK_PLAIN_ACCOUNT_KEY,
				// result.getAccount().getAcctNo());
				// 保存hashKey，用于输入密码用
				// mHTData.put(BANK_ACCOUNT_HASH_KEY,
				// result.getAccount().getAcctHashId());
			}

		} catch (Exception e) {
			HPLog.e(TAG, e.toString());
		}

		return swipeResult;

	}

	/**
	 * 将string转化为ascii
	 */
	private String StringToA(String content) {
		String result = "";
		int max = content.length();
		for (int i = 0; i < max; i++) {
			char c = content.charAt(i);
			String ss = Integer.toHexString((int) c);
			result = result + ss;
		}
		return result;
	}

	/**
	 * 超级转账模式下模式下，数据的处理
	 * 
	 * @param data
	 * @param keyIndex
	 * @return
	 */
	private String contentToEncry(String data, String keyIndex) {
		data = StringToA(data);
		// 只有做mac的时候，需要补80
		if (ISwiperListener.MacDataIndex.equals(keyIndex)) {
			data = data + "80";
		}
		StringBuilder builder;
		if (data.length() % 16 != 0) {
			builder = new StringBuilder();
			builder.append(data);
			while (builder.toString().length() % 16 != 0) {
				builder.append("0");
			}
			data = builder.toString();
		}
		return data;
	}

	String Emtd1, Emtd2, Emtd3,Emtd4;

	public boolean GetCipherTrackData() {
		OptResult = false;
		reader.getTrackDataCipher(new GetTrackDataCipherListener() {

			@Override
			public void onError(int errCode, String errDesc) {
				HPLog.i(TAG, "获取磁道失败" + errDesc);
				OptResult = false;
				mLock.unlock(AsynSwiperLock.CACL_DATA);
			}

			@Override
			public void onGetTrackDataCipherSucc(String track1, String track2, String track3,String expiredate) {
				HPLog.i(TAG, "获取磁道密文成功:磁道1：" + track1 + "磁道2：" + track2 + "磁道3" + track3);
				Emtd1 = track1;
				Emtd2 = track2;
				Emtd3 = track3;
				Emtd4  = expiredate;
				OptResult = true;
				mLock.unlock(AsynSwiperLock.CACL_DATA);
			}
		});

		try {
			mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_DATA);
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
		}

		return OptResult;
	}

	String encryptedData;

	private boolean encData(byte[] data) {
		encryptedData = "";

		if (isConnected() == false)
			return false;

		Map<Byte, byte[]> map = new HashMap<Byte, byte[]>();
		map.put((byte) 0, data);

		reader.getKey13Enc(map, new getKey13EncListener() {
			@Override
			public void onError(int errCode, String errDesc) {
				HPLog.i(TAG, "13加密失败: " + errDesc);
				OptResult = false;
				mLock.unlock(AsynSwiperLock.CACL_DATA);
			}

			@Override
			public void onGetKey13EncSucc(Map<Byte, String> responseMap) {
				responseMap.keySet();
				for (Byte key : responseMap.keySet()) {
					String value = responseMap.get(key);
					switch (key) {
					case 0:
						encryptedData = value;
						Log.e(TAG, "13加密成功: " + encryptedData);
						OptResult = true;
						mLock.unlock(AsynSwiperLock.CACL_DATA);
						break;
					}
				}
			}
		});

		try {
			mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_DATA);
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
		}

		return OptResult;
	}

	// private boolean encData(String data)
	// {
	// encryptedData="";
	//
	// if(isConnected()==false) return false;
	//
	// Map<Byte,String> map = new HashMap<Byte,String>();
	// map.put((byte) 0, data);
	//
	// reader.getKey13Enc(map, new getKey13EncListener() {
	// @Override
	// public void onError(int errCode, String errDesc) {
	// HPLog.i(TAG,"13加密失败: "+errDesc);
	// OptResult=false;
	// mLock.unlock(AsynSwiperLock.CACL_DATA);
	// }
	//
	// @Override
	// public void onGetKey13EncSucc(Map<Byte,String> responseMap) {
	// responseMap.keySet();
	// for (Byte key : responseMap.keySet())
	// {
	// String value = responseMap.get(key);
	// switch (key)
	// {
	// case 0:
	// encryptedData= value;
	// Log.e(TAG, "13加密成功: " + encryptedData);
	// OptResult=true;
	// mLock.unlock(AsynSwiperLock.CACL_DATA);
	// break;
	// }
	// }
	// }
	// });
	//
	// try {
	// mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_DATA);
	// } catch (TimeoutException te) {
	// HPLog.i(TAG, "", te);
	// }
	//
	// return OptResult;
	// }

	private boolean encMac(byte[] data) {

		String mac = CommonUtils.bytesToHexString(data);
		reader.calculateMac(CommonUtils.hexStringToBytes(mac), new CalcMacListener() {
			@Override
			public void onError(int errCode, String errDesc) {
				HPLog.i(TAG, "计算mac失败" + errDesc);
				OptResult = false;
				mLock.unlock(AsynSwiperLock.CACL_MAC);
			}

			@Override
			public void onCalcMacSucc(byte[] data1) {
				HPLog.i(TAG, "计算mac结果" + CommonUtils.bytesToHexString(data1));
				encryptedData = CommonUtils.bytesToHexString(data1).substring(0, 8);

				// comment by landi
				// // doBalanceEnquiry(time.toUpperCase(),
				// account.toUpperCase(), pin.toUpperCase(),
				// track.toUpperCase(), csn.toUpperCase(),
				// random.toUpperCase(), m_mac.toUpperCase());
				// comment by jason . not start from here.
				// data.put(255, m_mac.toUpperCase());
				// doUnionpay(data,"BalanceEnquiry");
				OptResult = true;
				mLock.unlock(AsynSwiperLock.CACL_MAC);
			}
		});

		try {
			mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_MAC);
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
		}

		return OptResult;
	}

	// refer to encData
	// private boolean encPin(byte[] data)
	// {
	//
	// return OptResult;
	// }

	public String encPan(String data) {
		boolean result = false;
		result = encData(data.getBytes());

		if (result == true)
			return encryptedData.toUpperCase(Locale.US);
		else
			return "";

	}

	@Override
	public String encData(String data, String index, String factor) {
		boolean result = false;
		HPLog.i(TAG, "data:");
		result = loadSeessionData(factor);
		if (result != true)
			return "";

		if (ISwiperListener.MacDataIndex.equals(index)) {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			try {
				bos.write(String.valueOf(data.toCharArray()).getBytes());
				bos.write(0x80);
				while (bos.size() % 8 != 0) {
					bos.write(0x00);
				}
				bos.write(0x80);
				for (int i = 0; i < 7; i++) {
					bos.write(0x00);
				}
				byte[] macPlainBytes = bos.toByteArray();
				HPLog.i(TAG, "mac :" + CommonUtils.bytesToHexString(macPlainBytes));
				result = encMac(macPlainBytes);
			} catch (IOException ioe) {
				HPLog.e(TAG, "", ioe);
				try {
					bos.close();
				} catch (IOException e) {
					HPLog.e(TAG, "", e);
				}
			}

		} else if (ISwiperListener.KeyDataIndex.equals(index)) {

			if (mFlag == SwiperMode.NORMAL_TRANS) {
				result = encData(CommonUtils.hexStringToBytes(data));
			} else {
				data = contentToEncry(data, index);
				result = encData(CommonUtils.hexStringToBytes(data));
			}
		} else if (PIN_INDEX.equals(index)) {
			// add by jh for test
			HPLog.e(TAG, "never should running here.");
			result = false;
			

		}

		HPLog.e(TAG, String.valueOf(result));
		if (result == true)
			return encryptedData.toUpperCase(Locale.US);
		else
			return "";
	}

	@Override
	public Hashtable<String, String> batchEncData(Hashtable<Integer, String> htDatas, String factor) {
		return null;
	}

	@Override
	public boolean setMode(SwiperMode flag) {
		mFlag = flag;
		clearData();

		return true;
	}

	private void clearData() {
		mAmount = null;
	}

	@Override
	public boolean isSwiperReady() {

		return mIsSwiperOK;
	}

	@Override
	public Result affirmAmount(String amount, int timeout) {
		mAmount = amount;

		return Result.OK;
	}

	String EncryptedPin;
	Result InputPinResult;

	public Result getReaderPwd() {
		HPLog.i(TAG, "getReaderPwd start");
		InputPinParameter inputPinParameter = new InputPinParameter();
		InputPinResult = Result.ERROR;

		inputPinParameter.setTimeout((byte) ZZTConstant.SWIPER_TIMEOUT);
		inputPinParameter.setAmount("");

		reader.inputPin(inputPinParameter, new InputPinListener() {
			@Override
			public void onError(int errCode, String errDesc) {
				HPLog.i(TAG, "读取PIN密钥失败" + errDesc);
				switch (errCode) {
				case 0x8E10:
					InputPinResult = Result.TIMEOUT;
					break;
				case 0x8E11:
					InputPinResult = Result.CANCEL;
					break;
				}

				mLock.unlock(AsynSwiperLock.NEW_INPUT_PWD);
			}

			@Override
			public void onInputPinSucc(byte[] pinblock) {
				HPLog.i(TAG, "读取PIN密钥成功" + CommonUtils.bytesToHexString(pinblock));
				EncryptedPin = CommonUtils.bytesToHexString(pinblock);
				InputPinResult = Result.OK;
				mLock.unlock(AsynSwiperLock.NEW_INPUT_PWD);
			}
		});

		try {
			mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.NEW_INPUT_PWD);
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
		}

		return InputPinResult;

	}

	@Override
	public Result inputPwd(String factor, int timeout) {
		HPLog.e(HPLog.FDL_TAG, "LandiSwiperBT:inputPwd>>>");
		Result PinResult = Result.ERROR;

		if (!isConnected()) {
			return PinResult;
		}

		// useless for landi
		// String accHashId = mHTData.get(BANK_ACCOUNT_HASH_KEY);

		String plainAcc = mHTData.get(BANK_PLAIN_ACCOUNT_KEY);
		String DCData = mHTData.get(BANK_DCDATA);
		String pin = mHTData.get(BANK_PAN_KEY);

		if (TextUtils.isEmpty(pin)) {
			// 前面貌似没有刷卡，报错！
			if (TextUtils.isEmpty(plainAcc)) {
				HPLog.e(TAG, "no card relative info.");
				return Result.ERROR;
			}

			PinResult = getReaderPwd();

			if (PinResult != Result.OK) {
				return PinResult;
			}
			// 如果用户没有输入密码，提示用户再次输入
			pin = EncryptedPin;
			if (pin != null && "FFFFFFFFFFFFFFFF".equalsIgnoreCase(pin)) {
				pin = null;
			}
		}

		// 新版 2.0.0 后加入IC 有效期 需要 13号密钥加密
		/*
		 * if (!TextUtils.isEmpty(mHTData
		 * .get(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE))) {
		 * HPLog.i(HPLog.FDL_TAG, "BusinessSwiper  encData-- plainExpireDate:" +
		 * mHTData.get(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE)); String exDate =
		 * encData( mHTData.get(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE),
		 * ISwiperListener.KeyDataIndex, factor); HPLog.i(HPLog.FDL_TAG,
		 * "BusinessSwiper enc return exDate:" + exDate); if
		 * (!TextUtils.isEmpty(exDate)) {
		 * mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, exDate); } else {
		 * HPLog.i("FDL", "enc plainExpireDate error!"); } }
		 */

		// 加密卡号。加密账号，需要先转化为hex。
		String encAcc = null;
		if (mFlag == SwiperMode.NORMAL_TRANS) {
			encAcc = encPan(plainAcc);
		} else if (mFlag == SwiperMode.SUPER_TRANS) {
			encAcc = encPan(plainAcc);
		}

		if (!TextUtils.isEmpty(pin) && !TextUtils.isEmpty(encAcc)) {
			mHTData.put(BANK_PAN_KEY, pin.toUpperCase(Locale.US));
			mHTData.put(BANK_ACCOUNT_KEY, encAcc);
			if (ClientEngine.getInstance().getGlobal(BANK_TransactionType_KEY) != null && ClientEngine.getInstance().getGlobal(BANK_TransactionType_KEY).equals("PurchaseAdvice")) {
				String merchantId = encData(ShowHtmlActivity.map.get("merchantId"), ISwiperListener.KeyDataIndex, factor);
				String orderId = encData(ShowHtmlActivity.map.get("orderId"), ISwiperListener.KeyDataIndex, factor);
				String terminalId = encData(ShowHtmlActivity.map.get("terminalId"), ISwiperListener.KeyDataIndex, factor);
				String transAmount = encData(CommonUtils.formatMoenyToUnionpay(ShowHtmlActivity.map.get("transAmount")), ISwiperListener.KeyDataIndex, factor);
				HPLog.e("merchantId", merchantId);
				HPLog.e("orderId", orderId);
				HPLog.e("terminalId", terminalId);
				HPLog.e("transAmount", transAmount);
				// 先保存为全局变量,备用
				ClientEngine.getInstance().saveGlobal(BANK_MerchantID_KEY, merchantId);
				ClientEngine.getInstance().saveGlobal(BANK_OrderID_KEY, orderId);
				ClientEngine.getInstance().saveGlobal(BANK_TerminalID_KEY, terminalId);
				ClientEngine.getInstance().saveGlobal(BANK_TransAmount_KEY, transAmount);
				mHTData.put(BANK_MerchantID_KEY, merchantId);
				mHTData.put(BANK_OrderID_KEY, orderId);
				mHTData.put(BANK_TerminalID_KEY, terminalId);
				mHTData.put(BANK_TransAmount_KEY, transAmount);
			}
			if (!TextUtils.isEmpty(mAmount) && Integer.parseInt(mAmount) > 0) {
				// 加密金额
				String encAmt;
				if (mAmount.length() == 10) {
					// 温旭东(328977974) 2014/11/28 11:18:05
					// 那金额问题跟123解释了，IC卡接口上送的金额格式和加密的金额是不一样的。IC卡上送的金额只是用来终端显示。格式应用那边可以自己转换下就可以
					String formatAmount = mAmount + "00";
					encAmt = encData(formatAmount, ISwiperListener.KeyDataIndex, factor);
				} else {
					encAmt = encData(mAmount, ISwiperListener.KeyDataIndex, factor);
				}

				if (!TextUtils.isEmpty(encAmt)) {
					mHTData.put(BANK_AMOUNT_KEY, encAmt);
					return Result.OK;
				}
				HPLog.i(TAG, "enc amount error!");
				return Result.ERROR;
			} else {
				return Result.OK;
			}
		} else {
			HPLog.e(TAG, "encData error!");
			return Result.ERROR;
		}
	}

	@Override
	public SwipeResult registerPwd(String factor, int timeout) {
		return null;
	}

	@Override
	public Hashtable<String, String> getBankInfo() {
		Hashtable<String, String> result = (Hashtable<String, String>) mHTData.clone();
		mHTData.clear();
		return result;
	}

	@Override
	public SwiperModel getSwiperModel() {
		return SwiperModel.M35_BLUETOOTH;
	}

	@Override
	public void setPlainPwd(String pwd) {

	}

	@Override
	public boolean printBitMap(int position, Bitmap bitmap) {
		return false;
	}

	@Override
	public boolean printString(String data) {
		return false;
	}

	@Override
	public boolean print(String data, Bitmap bitmap) {
		return false;
	}

}
